﻿WEBVTT

00:00:00.000 --> 00:00:06.000
Translated by visionNoob, KNU
https://github.com/insurgent92/CS231N_17_KOR_SUB

00:00:10.729 --> 00:00:12.896
시작하겠습니다.

00:00:16.381 --> 00:00:21.529
이번 시간에는 nerural network를 학습시키는 방법을
심도깊게 살펴보겠습니다.

00:00:23.166 --> 00:00:28.785
우선 공지사항먼저 전달드리자면
첫 번째 과제는 오늘까지입니다.

00:00:28.785 --> 00:00:36.521
금일 11:59 p.m 까지 Canvas에 제출해주시기 바라며,
더불어 과제 2가 새롭게 나갈 것입니다.

00:00:36.521 --> 00:00:40.082
그리고 여러분의 프로젝트 제안서는
25일까지 제출해 주시기 바랍니다.

00:00:40.082 --> 00:00:46.591
아직 준비가 안되신 분들이면 서둘러 해주시기 바랍니다.

00:00:46.591 --> 00:00:54.804
어느정도 구상한 분들이 계십니까?
몇 분정도 계시는군요

00:00:54.804 --> 00:01:03.937
어떻게 해야할지 모르겠다 싶으면
TA 사무실로 방문해 주시면 도와드리겠습니다.

00:01:05.657 --> 00:01:18.121
Piazza에 다른 연계 프로젝트도 있으니 확인해 주시기 바랍니다.

00:01:19.604 --> 00:01:28.004
그리고 Justin이 만든 "Linear Layer에서의 Backporp",
"vector/tensor 미분" 관련자료가 있으니 참고해주세요.

00:01:28.004 --> 00:01:33.964
이 자료를 보시면 vector/matrix에서 backporp이 어떻게
동작하는지 이해하실 수 있을 것입니다.

00:01:33.964 --> 00:01:40.484
Syllabus에 Lecture 4에 링크되어 있으니 보시면 됩니다.

00:01:45.110 --> 00:01:57.124
지난 시간에 함수를 computational graph로 표현하는
방법을 배웠습니다. 어떤 함수든 이렇게 표현할 수 있습니다.

00:01:57.124 --> 00:02:03.751
Neural network에 대해서 자세히 배웠습니다.
여기 보이는 것 처럼 Linear Layer들이 있었죠

00:02:03.751 --> 00:02:08.360
비 선형 연산자들을 끼워넣으면서 여러 층으로 쌓았습니다.

00:02:09.456 --> 00:02:13.360
지난 시간에 CNN도 배웠습니다.

00:02:13.360 --> 00:02:24.936
CNN은 "Spatial structure" 를 사용하기 위해
Conv Layer를 사용하는 NN의 특수한 형태이입니다.

00:02:24.936 --> 00:02:38.056
Conv 필터가 입력 이미지를 슬라이딩해서 계산한 값들이 모여
출력 Activation map을 만들게 됩니다.

00:02:38.056 --> 00:02:45.456
그리고 Conv layer는 대게 다수의 필터를 사용했습니다.
각 필터는 서로 다른 Activation map을 생성합니다.

00:02:45.456 --> 00:02:50.655
여기 그림은 보면 어떤 입력이 있고 Depth가 있습니다.
이제 Activation map 을 만들어야 하는데

00:02:50.655 --> 00:02:58.771
Activation map는 필터의 갯수만큼 존재하며 각 map은
입력의 공간적인 정보를 보존하고 있습니다.

00:02:59.695 --> 00:03:05.895
자 이제 우리가 하고싶은 것은 가중치, 즉 파라미터를
업데이트 하고 싶은 것입니다.

00:03:05.895 --> 00:03:12.507
지난 시간에 배웠듯이 Optimization을 통해서
네트워크의 파라미터를 학습할 수 있었습니다.

00:03:12.507 --> 00:03:17.254
그리고 Loss 라는 산에서 Loss가 줄어드는 방향으로
이동하고 싶은 것입니다.

00:03:17.254 --> 00:03:23.053
그리고 이는 gradient의 반대 방향으로 이동하는 것과 같습니다.

00:03:23.053 --> 00:03:27.614
이를 Mini-batch Stochastic Gradient Descent
이라고 했습니다.

00:03:27.614 --> 00:03:38.585
Mini-batch SGD는 우선 데이터의 일부만 가지고
Forword pass를 수행한 뒤에 Loss를 계산합니다.

00:03:38.585 --> 00:03:41.960
그리고 gradient를 계산하기 위해서
backprop를 수행합니다.

00:03:41.960 --> 00:03:47.986
그리고 그 gradient를 이용해서 파마미터를 업데이트합니다.

00:03:49.980 --> 00:03:58.321
향 후 몇번의 강의는 NN의 학습에 대해 다룰 것입니다.

00:03:58.321 --> 00:04:02.441
우선 NN 학습을 처음 시작할때 필요한 기본 설정에 대해 알아볼 것입니다.

00:04:02.441 --> 00:04:11.015
활성함수 선택, 데이터 전처리, 가중치 초기화
Regularization, gradient checking 등이 이에 속하죠

00:04:11.015 --> 00:04:16.118
또한 Training dynamics에 대해서도 다룰 것입니다.
학습이 잘 되고 있는지 확인하는 법에 대해 배울 것입니다.

00:04:16.118 --> 00:04:21.294
어떤 방식으로 파라미터를 업데이트할 것인지에 대해서도 배울 것이고

00:04:21.294 --> 00:04:26.241
가장 적절한 하이퍼파라미터를 찾기 위해
하이퍼파라미터를 Optimization 하는 방법도 배울 것입니다.

00:04:26.241 --> 00:04:28.281
그리고 평가에 대해서도 이야기 할 것입니다.

00:04:28.281 --> 00:04:29.948
그리고 Model ensemble에 대해서도 배웁니다.

00:04:33.000 --> 00:04:41.015
오늘은 Part 1 으로 활성함수, 데이터 전처리,
가중치 초기화, Batch Normalization

00:04:41.015 --> 00:04:45.412
학습 과정 다루기, 하이퍼 파라미터 Optimization 을
배워 보도록 하겠습니다.

00:04:47.348 --> 00:04:50.348
자 Activation Function 부터 시작해봅시다.

00:04:51.708 --> 00:04:55.095
자 먼저 지난시간에 봤던 Layer를 살펴보면

00:04:55.095 --> 00:05:01.481
데이터 입력이 들어오면 가중치와 곱합니다.
FC 나 CNN이 될 수 있겠죠

00:05:01.481 --> 00:05:06.388
그 다음 활성함수, 즉 비선형 연산을 거치게 됩니다.

00:05:06.388 --> 00:05:08.027
활성함수의 예시를 보겠습니다.

00:05:08.027 --> 00:05:13.295
지난 시간에 Sigmoid를 본적이 있죠
ReLU도 봤습니다.

00:05:13.295 --> 00:05:20.479
이번 시간에는 좀 더 다양한 종류의 활성함수와
그들간의 Trade-off에 대해 다뤄보도록 하겠습니다.

00:05:22.228 --> 00:05:27.241
자 우선 Sigmoid부터 보겠습니다.
우리한테 제일 만만한 놈이죠

00:05:27.241 --> 00:05:32.572
Sigmoid는 이렇게 생겼습니다.
1/(1+e^-x) 이죠

00:05:32.572 --> 00:05:45.201
얘가 하는 일은 각 입력을 받아서 그 입력을 [0, 1] 사이의
값이 되도록 해줍니다.

00:05:45.201 --> 00:05:50.427
입력의 값이 크면 Sigmoid의 출력은 1에 가까울 것이고

00:05:50.427 --> 00:05:55.321
값이 작으면 0에 가까울 것입니다.

00:05:55.321 --> 00:06:02.481
0 근처 구간(rigime)을 보면 선형스럽습니다 (/ 모양)
그 쪽은 선형함수 같아 보입니다.

00:06:02.481 --> 00:06:05.374
Sigmoid는 역사적으로 아주 유명했습니다.

00:06:05.374 --> 00:06:11.530
왜냐하면 Sigmoid가 일종의, 뉴런의 firing rate를
saturation 시키는 것으로 해석할 수 있기 때문입니다.

00:06:11.530 --> 00:06:15.455
어떤 값이 0에서 1 사이의 값을 가지면
이를 fireing rate라고 생각할 수 있을 것입니다.

00:06:15.455 --> 00:06:23.588
나중에 ReLU 같은 것을 배울 것인데, 실제로 ReLU가
생물학적 타당성이 더 크다는게 밝혀졌지만

00:06:23.588 --> 00:06:27.402
Sigmoid 또한 이런 식으로 해석할 수 있다는 점을
알고 넘어가면 될 것 같습니다.

00:06:30.015 --> 00:06:36.492
요 녀석을 한번 자세히 살펴보면
문제점이 몇 가지 있습니다.

00:06:36.492 --> 00:06:44.065
우선 Saturation되는게 gradient를 없앱니다.
이게 무슨 뜻일까요?

00:06:44.988 --> 00:06:48.801
이 Sigmoid gate를 Computraional graph에서
한번 살펴보겠습니다.

00:06:48.801 --> 00:06:54.566
여기 데이터 X가 있고 출력이 있습니다.

00:06:54.566 --> 00:06:59.236
Backprop에서 Gradient는 어떻게될까요?

00:06:59.236 --> 00:07:08.441
우선 dL/dSigma 가 있습니다. dL/dSigma가 밑으로
내려가죠 그리고 dX/dSigma를 곱하게 될 것입니다.

00:07:08.441 --> 00:07:11.081
이 값이 local sigmoid function의
gradient가 될 것입니다.

00:07:11.081 --> 00:07:16.495
그리고 이런 값들이 계속 연쇄적으로
Backporp될 것입니다.

00:07:16.495 --> 00:07:24.708
그렇다면 질문입니다. X가 -10이면 어떻게 될까요?
gradient는 어떻게 생기게 될까요?

00:07:24.708 --> 00:07:28.868
네 맞습니다. 0이 되겠죠.
gradient는 0이 됩니다.

00:07:28.868 --> 00:07:37.348
Sigmoid에서 음의 큰 값이면 sigmoid가
flat하게 되고 gradient가 0이 되겠죠

00:07:37.348 --> 00:07:40.001
그리고 이 값이 밑으로 내려갈 것입니다.

00:07:40.001 --> 00:07:46.501
거의 0에 가까운 값이 backprob 될 것입니다.

00:07:46.501 --> 00:07:55.381
이 부분에서 gradient가 죽어버리게 되고
밑으로 0이 계속 전달되게 됩니다.

00:07:58.869 --> 00:08:10.015
그렇다면 X가 0이면 어떻까요?
맞습니다. 이 구간에서는 잘 동작할 것입니다.

00:08:10.015 --> 00:08:15.135
아주 그럴싸한 gradient를 얻게 될 것이고
backprop 이 잘 될 것입니다.

00:08:15.135 --> 00:08:20.055
그러면 X가 10이면 어떻까요?

00:08:20.055 --> 00:08:31.108
X가 값이 큰 양수 일 경우에도 sigmoid가 flat하기
때문에 gradient들 다 죽이게 됩니다.

00:08:31.108 --> 00:08:35.275
그러면 gradient가 잘 흐르지 않겠죠

00:08:37.055 --> 00:08:42.454
두 번째 문제는 바로
sigmoid 의 출력이 zero centered 하지 않다는 것입니다.

00:08:42.454 --> 00:08:46.415
이게 왜 문제인지 한번 알아보도록 하겠습니다.

00:08:46.415 --> 00:08:51.892
자 그럼 뉴런의 입력이 항상 양수일 때
어떤 일이 벌어지는지 한번 살펴보겠습니다.

00:08:51.892 --> 00:08:54.948
이 경우에 모든 X가 양수일 때 입니다.

00:08:54.948 --> 00:09:04.348
이 x는 어떤 가중치랑 곱해지고 활성함수를 통과하겠죠

00:09:04.348 --> 00:09:08.015
그럼 W에 대한 gradient를 한번 생각해볼까요?

00:09:12.375 --> 00:09:18.135
이 Layer에서의 local gradient가 어떻게 될지
한번 생각해 보세요

00:09:18.135 --> 00:09:24.214
우선 dL/d(활성함수) 를 계산하겠죠 그렇게 Loss가 내려가고

00:09:24.214 --> 00:09:29.834
그리고 Local gradient가 있을텐데,
기본적으로 그냥 X입니다.

00:09:29.834 --> 00:09:34.001
그렇다면 모든 X가 양수라는 것은 무슨뜻일까요?

00:09:36.253 --> 00:09:44.401
누군가가 gradient가 전부 "양수" 가 된다고 하셨는데요.
정확히는 "전부 양수" 또는 "전부 음수" 입니다.

00:09:44.401 --> 00:09:53.588
위에서 dL/df(활성함수) 가 넘어오겠죠
이 값이 음수 또는 양수가 될 것입니다.

00:09:53.588 --> 00:09:55.815
어떤 임의의 gradient가 내려온다고 생각해 봅시다.

00:09:55.815 --> 00:10:06.619
우선 local gradient는 이 값이랑 곱해질 것이고
dF(활성함수)/dW는, 그냥 X가 될 것입니다.

00:10:07.880 --> 00:10:20.800
그렇게 되면 gradient의 부호는 그저
위에서 내려온 gradient의 부호과 같아 질 것입니다.

00:10:20.800 --> 00:10:28.520
이것이 의미하는 바는 W가 모두 같은 방향으로만 움직일 것임을
의미하게 됩니다.

00:10:28.520 --> 00:10:42.467
파라미터를 업데이트 할 때 다 같이 증가하거나
다 같이 감소하거나 할 수 밖에 없습니다.

00:10:42.467 --> 00:10:48.867
여기서의 문제는 이런 gradient 업데이트는
아주 비효율적이라는 것입니다.

00:10:48.867 --> 00:10:59.507
여기 W가 이차원인 예제가 있습니다.
W에 대한 두개의 축으로 이루어져 있습니다.

00:10:59.507 --> 00:11:04.796
전부 양수 또는 음수로 업데이트된다는 것을 해석해보면

00:11:04.796 --> 00:11:12.400
이렇게 되면 gradient가 이동할 수 있는 방향은 4분면 중
이 두 영역뿐이 안 될 것입니다.

00:11:12.400 --> 00:11:17.213
이 두 방향으로 밖에 gradient가 업데이트되지 않습니다.

00:11:17.213 --> 00:11:25.399
그래서 이론적으로 가장 최적의 W 업데이트가
저 파란색 화살표이고

00:11:25.399 --> 00:11:30.773
우리가 어떤 초기 시작점부터 내려간다고 했을 때
시작점은 빨간 화살표의 맨 처음 부분입니다.

00:11:30.773 --> 00:11:38.946
하지만 gradient는 파란색 방향으로 내려갈 수 없습니다.
그 방향으로는 움직일 수 없기 때문이죠

00:11:38.946 --> 00:11:43.479
그렇기 때문에 우리는 여러번 gradient 업데이트를
수행해 줘야 합니다.

00:11:43.479 --> 00:11:51.953
가령 이렇게 빨간 화살표 방향와 같이, gradient가 이동 가능한
방향으로만 이동을 할 수 있게 됩니다.

00:11:53.039 --> 00:11:58.479
이것이 바로 우리가 일반적으로
zero-mean data을 원하는 이유입니다.

00:11:58.479 --> 00:12:11.893
입력 X가 양수/음수를 모두 가지고 있으면  전부 같은 방향으로 움직이는
일은 발생하지는 않을 것입니다.

00:12:11.893 --> 00:12:17.819
이해 하셨습니까? 질문 있으신가요?
좋습니다.

00:12:21.453 --> 00:12:24.930
자 우리는 지금까지 sigmoid가 가진 문제에 대해서 배웠습니다.

00:12:24.930 --> 00:12:30.586
Saturation이 gradient를 죽일 수 있었습니다.
양/음의 방향으로 너무 큰 값을 가진다면 말이죠

00:12:30.586 --> 00:12:36.586
그리고 zero-centered 가 아니기 때문에
gradient 업데이트가 효율적이지 않았습니다.

00:12:36.586 --> 00:12:43.146
그리고 세 번째 문제는 exp()로 인해
계산비용이 크다는 것입니다.

00:12:43.146 --> 00:12:46.837
이 세 번째 문제는 그렇게 큰 문제는 아닙니다.

00:12:46.837 --> 00:12:51.186
큰 그림으로 봤을 때 다른 연산들, 가령
내적의 더 계산이 비쌉니다.

00:12:51.186 --> 00:12:55.103
하지만 굳이 문제로 뽑자면 이렇다는 것입니다.

00:12:58.986 --> 00:13:03.166
이제 두 번째 활성 함수를 한번 보겠습니다.
tanh입니다.

00:13:03.166 --> 00:13:10.999
sigmoid 랑 유사하죠. 하지만 범위가 [-1 , 1] 입니다.

00:13:10.999 --> 00:13:15.573
가장 큰 차이점이 있다면
이제 zero-centered 라는 것입니다.

00:13:15.573 --> 00:13:21.306
이를 통해 두 번째 문제가 해결됩니다. 하지만
saturation때문에 여전히 Gradient가 죽습니다.

00:13:21.306 --> 00:13:29.264
여기 보시면 여전히 gradient가 평평해 지는 구간이 있겠죠

00:13:29.264 --> 00:13:34.009
tanh는 sigmoid보다는 조금 낫지만
그래도 여전히 문제점은 있습니다.

00:13:36.586 --> 00:13:40.104
자 이제 ReLU 를 살펴보겠습니다.

00:13:40.104 --> 00:13:47.573
CNN 강의할 때 본 적 있으실 것입니다.

00:13:47.573 --> 00:13:53.279
Conv layer들 사이 사이에 ReLU가 있었죠

00:13:53.279 --> 00:13:58.253
ReLU의 함수는
f(x) = max(0,x) 입니다.

00:13:58.253 --> 00:14:06.573
이 함수는 element-wise 연산을 수행하며
입력이 음수면 값이 0이 됩니다.

00:14:06.573 --> 00:14:13.264
그리고 양수면 입력 값 그대로를 출력합니다.

00:14:13.264 --> 00:14:22.892
ReLU는 상당히 자주 쓰입니다. 그리고 기존 sigmoid와 tanh한테
있었던 문제점들을 한번 살펴보자면

00:14:22.892 --> 00:14:26.746
우선 ReLU는 양의 값에서는 saturetion되지 않습니다.

00:14:26.746 --> 00:14:34.465
적어도 입력스페이스의 절반은 saturation 되지 않을 것입니다.
ReLU의 가장 큰 장점이죠

00:14:34.465 --> 00:14:36.959
그리고 계산 효율이 아주 뛰어납니다.

00:14:36.959 --> 00:14:42.466
기존의 sigmoid는 함수 안에 지수 항이 있었죠

00:14:42.466 --> 00:14:48.968
반면에 ReLU는 단순히 max 연산이므로
계산이 매우 빠릅니다.

00:14:48.968 --> 00:14:57.063
ReLU를 사용하면 실제로  sigmoid나 tanh보다 수렴속도가
훨씬 빠릅니다. 거의 6배정도 더 빠르죠

00:14:57.063 --> 00:15:01.090
그리고 사실 생물학적 타당성도 ReLU가 sigmoid보다 큽니다.

00:15:01.090 --> 00:15:11.450
실제 신경과학적인 실험을 통해서 뉴런을 관찰해보면

00:15:11.450 --> 00:15:18.303
실제 뉴런의 입/출력 값을 확인해보면 sigmoid보다
ReLU 스럽다는 것을 알 수 있습니다.

00:15:18.303 --> 00:15:33.798
ImageNet 2012에서 우승한 AlexNet이 처음 ReLU를
사용하기 시작했습니다.

00:15:36.775 --> 00:15:42.082
그런데 ReLU에 문제가 하나 있다면 ReLU는 더이상
zero-centered가 아니라는 것입니다.

00:15:42.082 --> 00:15:49.228
tanh가 이 문제는 해결했는데 ReLU는 다시 이 문제를
가지고 있게 됩니다.

00:15:49.228 --> 00:15:52.122
이는 ReLU가 가진 이슈중 하나입니다.

00:15:52.122 --> 00:15:55.357
그리고 ReLU가 가진 골칫거리가 하나 더 있습니다.

00:15:55.357 --> 00:16:04.222
ReLU에서 양의 수에서는 saturation 되지 않지만
음의 경우에서는 그렇지 않습니다.

00:16:04.222 --> 00:16:06.882
좀 더 자세히 알아보겠습니다.

00:16:06.882 --> 00:16:11.255
X가 -10이면 어떻게 될까요?

00:16:11.255 --> 00:16:12.855
gradient가 0이 되겠죠

00:16:12.855 --> 00:16:16.522
그렇다면 x가 10일때는 어떻게 될까요?

00:16:17.455 --> 00:16:20.175
맞습니다.
선형 영역(linear regime)에 속합니다.

00:16:20.175 --> 00:16:30.442
x가 0일 때는 어떨까요? 물론 여기에서는 정의되지 않지만
실제로는 0입니다.

00:16:30.442 --> 00:16:35.074
기본적으로 ReLU는 gradient의 절반을 죽여버리는 셈입니다.

00:16:37.948 --> 00:16:45.708
그래서 우리는 dead ReLU 라는 현상을 겪을 수 있습니다.

00:16:45.708 --> 00:16:51.212
이런 일은 몇 가지 상황에서 발생할 수 있는데

00:16:51.212 --> 00:16:57.192
자 여기 data cloud가 있습니다.
여러분이 가진 traing data라고 생각하시면 됩니다.

00:16:59.033 --> 00:17:09.092
ReLU에서는 평면의 절반만 activate 된다는 것을 알 수 있습니다.

00:17:11.948 --> 00:17:15.640
각 평면(초록 빨강 직선)이 각 ReLU를 의미한다고 보시면 됩니다.

00:17:15.640 --> 00:17:21.201
그리고 ReLU가 data cloud에서 떨어져 있는 경우에
"dead ReLU" 가 발생할 수 있습니다.

00:17:21.201 --> 00:17:26.588
dead ReLU에서는 activate 가 일어나지 않고
update되지 않습니다. 반면 active ReLU는

00:17:26.588 --> 00:17:31.732
일부는 active되고 일부는 active하지 않을 것입니다.

00:17:31.732 --> 00:17:33.480
몇 가지 이유로 이런 일이 발생할 수 있습니다.

00:17:33.480 --> 00:17:37.201
우선 첫 번째로는
초기화를 잘 못한 경우 입니다.

00:17:37.201 --> 00:17:45.015
여기 dead ReLU 처럼 생긴 경우인데, 가중치 평면이
data cloud에서 멀리 떨어져 있는 경우입니다.

00:17:45.015 --> 00:17:55.069
이런 경우 어떤 데이터 입력에서도 activate 되는 경우가
존재하지 않을 것이고 backporp이 일어나지 않을 것입니다.

00:17:56.108 --> 00:17:59.321
이런 경우 update되지도 activate되지도 않을 것입니다.

00:17:59.321 --> 00:18:03.880
그리고 더 흔한 경우는
Leraning rate가 지나치게 높은 경우입니다.

00:18:03.880 --> 00:18:11.561
처음에 "적절한 ReLU" 로 시작할 수 있다고 해도 만약
update를 지나치게 크게 해 버려 가중치가 날뛴다면

00:18:11.561 --> 00:18:18.028
ReLU 가 데이터의 manifold를 벗어나게 됩니다.
이런 일들은 학습과정에서 충분히 일어날 수 있습니다.

00:18:18.028 --> 00:18:22.975
그래서 처음에는 학습이 잘 되다가
갑자기 죽어버리는 경우가 생기는 것입니다.

00:18:22.975 --> 00:18:24.108
그리고 실제로,

00:18:24.108 --> 00:18:33.361
그리고 실제로 학습을 다 시켜놓은 네트워크를 살펴보면
10~20% 가량은 dead ReLU가 되어 있습니다.

00:18:33.361 --> 00:18:40.001
이게 문제이긴 하지만 ReLU를 사용하고 있다면 대부분의
네트워크가 이 문제를 겪을 수 있습니다.

00:18:40.001 --> 00:18:49.467
일부는 dead ReLU가 되버리는 것을 관찰해 볼 수 있습니다.
하지만 그 정도면 네트워크 학습에 크게 지장이 있진 않습니다.

00:18:49.467 --> 00:18:51.268
질문 있나요?

00:18:51.268 --> 00:18:54.851
[학생이 질문]

00:19:01.908 --> 00:19:05.335
네 맞습니다.
Data cloud는 그냥 training data입니다.

00:19:05.335 --> 00:19:08.918
[학생이 질문]

00:19:17.641 --> 00:19:25.708
질문은 바로 data cloud에서 ReLU가 죽어버리는지 아닌지를
어떻게 알 수 있냐느 것입니다.

00:19:25.708 --> 00:19:30.988
여기 예를 다시 한 번 보겠습니다.
간단한 2차원의 경우입니다.

00:19:30.988 --> 00:19:42.278
ReLU의 입력 값은 가령  W1*X1 + W2*X2 같은 값이 되겠죠

00:19:42.278 --> 00:19:46.080
그리고 이 가중치가 초평면(초록 빨강)을 이루게 되겠죠

00:19:46.080 --> 00:19:51.453
그리고 여기에서 positive인 절반만 가져갈 것입니다.
나머지 절반은 죽어버리겠죠

00:19:51.453 --> 00:20:03.789
그러니 W의 초평면의 위치와 Data의 위치를 고려했을 때
초평면 자체가 Data와 동떨어지는 경우가 발생할 수 있습니다.

00:20:05.560 --> 00:20:14.329
학습 과정에서 일부 ReLU는 data cloud와 동떨어져
있을 수가 있습니다.

00:20:16.480 --> 00:20:18.050
질문 있나요?

00:20:18.050 --> 00:20:21.633
[학생이 질문]

00:20:23.380 --> 00:20:33.478
sigmoid의 두 가지 단점에 중에서 하나가 뉴런이
saturation 된다는 것이었습니다.

00:20:37.045 --> 00:20:40.500
sigmoid 슬라이드를 다시한번 보겠습니다.

00:20:40.500 --> 00:20:45.820
질문은 바로 input이 전부 positive면
saturation이 안되지 않냐는 것입니다.

00:20:45.820 --> 00:20:51.971
여기 입력이 모두 양수면
0의 오른쪽 지역으로 들어오는 것이겠죠

00:20:51.971 --> 00:20:54.464
그렇게 되도 여전히 saturation의 가능성이 있습니다.

00:20:54.464 --> 00:21:00.544
왜냐하면 positive region에서도 여전히
평평한 곳이 존재하기 때문입니다.

00:21:00.544 --> 00:21:08.846
양의 큰 값이 들어오면, 여기 평평한 지역 때문에 여전히
gradient가 0이 될 수 있을 것입니다.

00:21:10.715 --> 00:21:11.548
좋습니다.

00:21:16.355 --> 00:21:24.528
그래서 실제로 ReLU를 초기화할때
positive biases를 추가해 주는 경우가 있습니다.

00:21:24.528 --> 00:21:30.721
Update 시에 active ReLU가 될 가능성을 조금이라도 더
높혀주기 위해서죠

00:21:30.721 --> 00:21:40.430
하지만 이게 도움이 된다는 의견도 있고
그렇지 않다는 사람들도 있습니다.

00:21:40.430 --> 00:21:48.072
이 방법을 항상 사용하지는 않고, 대부분은 사람들은
zero-bias로 초기화합니다.

00:21:49.483 --> 00:21:54.777
ReLU 이후에 조금 수정된 버전이 나왔습니다.

00:21:54.777 --> 00:21:57.768
그 중 하나가 바로 leaky ReLU 라는 녀석입니다.

00:21:57.768 --> 00:22:04.429
ReLU와 유사하지만 negarive regime에서
더 이상 0이 아닙니다.

00:22:04.429 --> 00:22:11.955
negative에도 기울기를 살짝 주게 되면 앞서 설명했던
문제를 상당 부분 해결하게 됩니다.

00:22:11.955 --> 00:22:17.142
Leaky ReLU의 경우에는 negative space 에서도
saturation 되지 않습니다.

00:22:17.142 --> 00:22:23.968
여전히 계산이 효율적입니다. 그리고 sigmoid 나 tanh보다
수렴을 빨리 할 수 있습니다. 그리고 ReLU랑도 비슷하게 생겼죠

00:22:23.968 --> 00:22:27.218
그리고 dead ReLU 현상도 더 이상 없습니다.

00:22:28.923 --> 00:22:35.380
또 다른 예시로는
parametric rectifier,  PReLU 가 있습니다.

00:22:35.380 --> 00:22:42.195
PReLU는 negative space에 기울기가 있다는 점에서
Leaky ReLU와 유사하다는 것을 알 수 있습니다.

00:22:42.195 --> 00:22:47.088
다만 여기에서는 기울기가 alpha 라는
파라미터로 결정됩니다.

00:22:47.088 --> 00:22:52.982
alpha를 딱 정해놓는 것이 아니라 backpro으로
학습시키는 파라미터로 만든 것입니다.

00:22:52.982 --> 00:22:57.555
활성함수가 조금 더 유연해 질 수 있을 것입니다.

00:22:57.555 --> 00:23:02.342
또 다른 예시로
ELU라는 것도 있습니다.

00:23:02.342 --> 00:23:08.295
우리는 지금 LU 패밀리들을 보고 있습니다.

00:23:08.295 --> 00:23:10.341
ELU는 ReLu의 이점을 그대로 가져옵니다.

00:23:10.341 --> 00:23:14.508
하지만 ELU는 zero-mean 에 가까운 출력값을 보입니다.

00:23:16.181 --> 00:23:24.901
zero-mean에 가까운 출력은 앞서 leaky ReLU, PReLU
가 가진 이점이었죠

00:23:26.699 --> 00:23:36.538
하지만 Leaky ReLU와 비교해보면 ELU는 negative에서
"기울기" 를 가지는 것 대신에 또 다시 "saturation" 됩니다.

00:23:36.538 --> 00:23:43.029
ELU가 주장하는건 이런 saturation이 좀더
잡음(noise)에 강인할 수 있다는 것입니다.

00:23:43.029 --> 00:23:48.566
이런 deactivation이 좀더 강인함을 줄 수 있다고 주장합니다.

00:23:48.566 --> 00:23:55.885
ELU의 논문에서는 왜 ELU가 더 강인한지에
타당성을 다양하게 제시하고 있습니다.

00:23:55.885 --> 00:24:01.111
ELU는 ReLU와 Leaky ReLU의 중간 정도라고 보시면 됩니다.

00:24:01.111 --> 00:24:13.267
ELU는 Leaky ReLU처럼 zero-mean의 출력을 내지만
Saturation의 관점에서 ReLU의 특성도 가지고 있습니다.

00:24:13.267 --> 00:24:14.350
질문 있나요?

00:24:14.350 --> 00:24:17.933
[학생이 질문]

00:24:19.952 --> 00:24:24.365
질문은 바로 파라미터 alpha가 각 뉴런마다
제각각이냐는 것입니다.

00:24:24.365 --> 00:24:34.090
아마 각각일 것 같은데 정확히 기억나지 않습니다.
논문에서 어떻게 정의하였는지를 보시면 될 것 같습니다.

00:24:35.578 --> 00:24:45.050
하지만 확실한 것은 ELU가 좋은 장점을 지니도록
세심하게 디자인하였다는 것입니다.

00:24:45.050 --> 00:24:49.992
지금까지는 ReLU의 변종들이었습니다.

00:24:49.992 --> 00:24:58.192
다양한 활성함수들이 어떤 장단점이 있는지를
여러분 스스로 눈여겨 볼 수 있을 것입니다.

00:24:58.192 --> 00:25:04.950
실제로 사람들이 이것저것 실험해보고 경험적으로 어떤 것이
더 좋은지를 살펴보고 새로운 것들을 만들어낸 것입니다.

00:25:04.950 --> 00:25:08.612
이들 모두는 실험해볼만한 것들이라 할 수 있겠습니다.

00:25:10.135 --> 00:25:14.744
그럼 하나만 더 알아보겠습니다.
Maxout Neuron 이라는 것입니다.

00:25:14.744 --> 00:25:25.969
지금까지 본 활성함수들과는 좀 다르게 생겼습니다. 입력을
받아드리는 특정한 기본형식을 미리 정의하지 않습니다.

00:25:25.969 --> 00:25:34.670
대신에 w1에 x를 내적한 값 + b1과 w2에 x를 내적한 값 + b2
의 최댓값을 사용합니다.

00:25:38.230 --> 00:25:43.185
Maxout은 이 두 함수 중 최댓값을 취합니다.

00:25:44.870 --> 00:25:48.949
Maxout는 ReLU와 leaky ReLU의 좀 더 일반화된 형태입니다.

00:25:48.949 --> 00:25:54.112
왜냐하면 Maxout은 이 두 개의 선형함수를 취하기 때문이죠

00:25:55.023 --> 00:26:02.927
Maxout또한 선형이기때문에 saturation 되지 않으며
gradient가 죽지 않을 것입니다.

00:26:02.927 --> 00:26:15.984
여기서 문제점은 뉴런당 파라미터의 수가 두배가 된다는 것입니다.
이제는 W1과 W2를 지니고 있어야합니다.

00:26:17.765 --> 00:26:24.560
지금까지 다양한 활성함수를 살펴보았습니다. 실제로
가장 많이들 쓰는 것은 바로 ReLU 입니다.

00:26:24.560 --> 00:26:29.389
ReLU가 표준으로 많이 사용되며
대게는 잘 동작합니다

00:26:30.231 --> 00:26:36.497
다만 ReLU를 사용하려면 leraning rate를 아주 조심스럽게
결정해야 할 것입니다.

00:26:36.497 --> 00:26:40.091
learning rate에 관해서는 이번 강의의 후반부에 좀 더
다뤄보도록 하겠습니다.

00:26:40.091 --> 00:26:52.318
또한 여러분은 Leaky ReLU, Maxout, ELU와 같은 것들도
써볼 수 있겠습니다. 물론 이들은 아직 실험단계이긴 합니다.

00:26:53.828 --> 00:26:56.643
여러분들의 문제에 맞춰 어떤 활성함수가 잘 동작하는지
확인해 볼 수 있을 것입니다.

00:26:56.643 --> 00:27:04.035
tanh도 써볼 수 있겠죠. 하지만 대게는 ReLU와 ReLU의 변종들이
좀 더 잘 동작한다고 보시면 되겠습니다.

00:27:04.035 --> 00:27:15.243
Sigmoid는 사용하지 않는 편이 좋습니다. 가장 구식이고
요즘은 LU 패밀리 계열이 더 잘 동작합니다.

00:27:17.361 --> 00:27:21.517
자 그럼 이제 데이터 전처리에 대해 배워보겠습니다.

00:27:21.517 --> 00:27:24.602
지금까지는 활성 함수에 대해 배워보았습니다.

00:27:24.602 --> 00:27:30.361
이제는 실제로 네트워크를 훈련시켜 보려 합니다.
우선 우리에게는 입력 데이터가 있겠죠.

00:27:31.424 --> 00:27:39.495
일반적으로 입력 데이터는 전처리를 해줍니다.
Machine Learning 수업에서 다뤄 보신 분들도 계실 것입니다.

00:27:39.495 --> 00:27:49.366
가장 대표적인 전처리 과정은
"zero-mean"으로 만들고 "normalize" 하는 것입니다.

00:27:49.366 --> 00:27:57.367
normalization은 보통 표준편차로 합니다.
그렇다면 이걸 왜 하는 것일까요?

00:27:57.367 --> 00:28:04.979
앞서 zero-centering에 대해 다룬 적이 있었죠.
입력이 전부 positive인 경우에 대해 말이죠

00:28:04.979 --> 00:28:12.772
그러면 모든 뉴런이 positive인 gradient를 얻게 됩니다.
이는 최적하지 못한(suboptimal) 최적화가 됩니다.

00:28:12.772 --> 00:28:21.710
데이터가 전부 positive 일 때 뿐만이 아니라 0 이거나
전부 negative일 경우에도 이런 일은 발생하곤 합니다.

00:28:23.770 --> 00:28:36.440
normalization을 해주는 이유는 모든 차원이 동일한 범위안
있게 해줘서 전부 동등한 기여(contribute)를 하게 합니다.

00:28:36.440 --> 00:28:45.866
실제로는 이미지의 경우 전처리로 zero-centering 정도만 해주니다.

00:28:45.866 --> 00:28:56.616
normalization 하지는 않습니다. 왜냐하면 이미지는
이미 각 차원 간에 스케일이 어느정도 맞춰져 있기 때문입니다.

00:28:56.616 --> 00:29:09.339
따라서 스케일이 다양한 여러 ML 문제와는 달리 이미지에서는
normalization을 엄청 잘 해줄 필요는 없습니다.

00:29:11.037 --> 00:29:19.983
그리고 Machine learning 에서는 PCA나 whitening 같은
더 복잡한 전처리 과정도 있긴 합니다만

00:29:19.983 --> 00:29:28.678
이미지에서는 단순히 zero-mean 정도만 사용하고 normalization
그 밖의 여러 복잡한 방법들은  잘 안씁니다.

00:29:29.519 --> 00:29:40.876
일반적으로는 이미지를 다룰 때는 굳이 입력을
더 낮은 차원으로  projection 시키지 않습니다.

00:29:40.876 --> 00:29:48.184
CNN에서는 원본 이미지 자체의 spatial 정보를 이용해서
이미지의 spatial structure를 얻을 수 있도록 합니다.

00:29:48.184 --> 00:29:49.595
질문 있나요?

00:29:49.595 --> 00:29:53.178
[학생이 질문]

00:29:58.858 --> 00:30:06.968
질문은 Train Phase에서 전처리를 해줬으면 Test Phase
에서도 똑같은 전처리를 해 줘야 하는 것인 인데, 맞습니다.

00:30:06.968 --> 00:30:24.839
일반적으로 Train에서 계산한 평균을 Test데이터에도 동일하게 적용해
줍니다. Training data에서 구한 평균을 그대로 사용하죠

00:30:24.839 --> 00:30:35.822
요약해보자면 이미지를 다룰때는
기본적으로 zero-mean 으로 전처리를 해준다는 것입니다.

00:30:38.151 --> 00:30:41.354
평균 값은 전체 Training data에서 계산합니다.

00:30:41.354 --> 00:30:54.777
보통 입력이미지의 사이즈를 서로 맞춰주는데 가령 32x32x3 이고
네트워크에 들어가기 전에 평균값을 빼주게 됩니다.

00:30:54.777 --> 00:31:00.532
그리고 Test time의 이미지에도 Training time에 계산한
평균 값으로 빼주게 됩니다.

00:31:00.532 --> 00:31:14.916
실제로 일부 네트워크는 채널 전체의 평균을 구하지 않고 채널마다
평균을 독립적으로 계산하는 경우도 있습니다.

00:31:14.916 --> 00:31:25.718
채널별로 평균이 비슷할 것인지 아니면 독립적으로
계산해야 할 것인지는 여러분이 판단하기 나름입니다.

00:31:25.718 --> 00:31:36.936
AlexNet 이후 VGGNet 같은 네트워크가 이러한 형태인데
추후에 다시 다루도록 하겠습니다.

00:31:36.936 --> 00:31:38.545
질문 있나요?

00:31:38.545 --> 00:31:42.128
[학생이 질문]

00:31:45.215 --> 00:31:52.049
질문은 두 가지 하셨습니다. 우선 첫 번째 질문은
"채널 의 의미" 입니다.

00:31:52.049 --> 00:32:04.198
여기에서 채널은 RGB입니다. 이미지가 32x32x3 이면
Width(32) x Height(32) x RGB(3) 입니다.

00:32:04.198 --> 00:32:09.786
VGG식으로 하면 RGB별로 각각 평균을 구하는 것입니다.

00:32:09.786 --> 00:32:14.529
두 번째 질문이 무엇이었죠?

00:32:14.529 --> 00:32:18.112
[학생이 질문]

00:32:21.349 --> 00:32:26.827
질문은 "평균 을 어떻게 계산하는지" 입니다.

00:32:27.882 --> 00:32:39.114
평균은 여러분의 "학습 데이터 전부" 를 가지고 계산합니다.
이해가 되셨습니까?

00:32:39.114 --> 00:32:42.697
[학생이 질문]

00:32:48.432 --> 00:32:55.255
질문은 만약 미니배치 단위로 학습시킨다고 해도 평균 계산은
미니배치 단위로 각각이 아니라 전체로 계산하냐는 것입니다.

00:32:55.255 --> 00:32:57.904
맞습니다.

00:32:57.904 --> 00:33:03.984
우리가 구하는 평균 이라는 것은 트레이닝 데이터의 평균입니다.

00:33:03.984 --> 00:33:13.983
배치에서 뽑은 데이터도 사실 전체 데이터에서 나온 것들이죠
결국은 배치 평균이나 전체 평균이나 구해보면 같습니다.(이상적으로)

00:33:13.983 --> 00:33:19.126
그러니 처음에 전체 트레이닝 이미지를 이용하여
단 한번만 평균을 계산 해 놓는 편이 낫습니다.

00:33:19.126 --> 00:33:28.296
반대로 엄청 큰 데이터의 전체 평균을 구할때도 굳이 모든 데이터를
전부 쓰지 않고 적절하게 샘플링해서 구할수도 있겠죠

00:33:30.734 --> 00:33:35.560
좋습니다. 혹시 다른 질문도 있으십니까?

00:33:35.560 --> 00:33:38.654
[학생이 질문]

00:33:38.654 --> 00:33:42.187
질문은 바로 데이터 전처리가 Sigmoid Problem을
해결할 수 있는지 입니다.

00:33:42.187 --> 00:33:46.354
우리가 수행 할 전처리는 zero mean 입니다.

00:33:47.540 --> 00:33:50.535
앞서 sigmoid 에게는 zero-mean이 필요하다고 했습니다.

00:33:50.535 --> 00:33:56.262
데이터 전처리가 sigmoid의 zero-mean 문제를
단지 "첫 번째" 레이어에서만 해결할 수 있을 것입니다.

00:33:56.262 --> 00:34:00.263
처음에는 입력 이미지가 zero-mean 이므로 해결 할 순 있겠으나

00:34:00.263 --> 00:34:08.472
하지만 그 다음 레이어부터는 똑같은 문제가 반복될 것입니다.
Deep network라면 점점 더 심해지겠죠

00:34:08.472 --> 00:34:12.437
가면 갈수록 더 non-zero-mean 을 겪게 될 것입니다.

00:34:12.438 --> 00:34:19.350
따라서 이미지 전처리가 Sigmoid에서의 문제를 해결하기에는
충분하지 않을 것입니다.

00:34:21.784 --> 00:34:28.203
좋습니다. 이제 weight를 어떻게 초기화시켜야
하는지를 알아보겠습니다.

00:34:28.204 --> 00:34:34.471
"Two Layer Neural Network" 예시를 한번 봅시다.
우리가 할 일은 가중치 업데이트입니다.

00:34:34.472 --> 00:34:43.509
맨 처음에 어떤 초기 가중치들이 있겠죠
그리고 gradient를 계산해서 가중치를 업데이트할 것입니다.

00:34:43.510 --> 00:34:56.157
첫 번째 질문입니다.  "모든 가중치 = 0" 이면 어떻게 될까요?
모든 파라미터를 0으로 세팅하면 어떻게될까요

00:34:56.157 --> 00:34:58.683
[학생이 대답]

00:34:58.683 --> 00:35:00.766
잘 못들었습니다?

00:35:02.039 --> 00:35:08.320
"모든 뉴런이 죽어버리고 업데이트가 되지 않을것이다"고 답했습니다.
정확한 답은 아닙니다.

00:35:11.035 --> 00:35:16.995
그래도 잘 대답하신 부분은 "모든 뉴런이 &lt;같은일&gt; 을 한다는 것" 입니다.
그렇다고 다 죽어버리지는 않습니다.

00:35:16.995 --> 00:35:23.321
입력 데이터들이 뉴런의 어떤 영역에 속할 것이고
죽지 않을 수도 있습니다.

00:35:23.321 --> 00:35:27.869
하지만 중요한 것은
전부 똑같은 일을 할 것이라는 것입니다.

00:35:27.869 --> 00:35:36.577
가중치가 0 이라서 모든 뉴런은 모두 다 같은 연산을 수행합니다.

00:35:36.577 --> 00:35:43.621
출력도 모두 같을 것이고. 결국 gradient도 서로 같습니다.

00:35:43.621 --> 00:35:47.571
결국 모든 가중치가 똑같은 값으로 업데이트 됩니다.

00:35:47.571 --> 00:35:51.983
결국 모든 뉴런이 모두 똑같이 생기게 됩니다.
우리가 그다지 원하는 것은 아니죠

00:35:51.983 --> 00:35:54.075
우리는 뉴런들이 서로 다르게 생기길 원하죠

00:35:54.075 --> 00:35:58.514
이것이 바로 모든 가중치를 동일하게 초기화시키면
발생하는 일입니다.

00:35:58.514 --> 00:36:02.730
"Symmetry breaking"이 일어날 수 없습니다.

00:36:02.730 --> 00:36:05.961
질문 있나요?

00:36:05.961 --> 00:36:09.544
[학생이 질문]

00:36:19.699 --> 00:36:29.961
질문은 gradient는 가중치 뿐만 아니라 Loss의 영향도 받으므로
결국 각각의 gradient는 다를 것이지 않냐는 것입니다.

00:36:29.961 --> 00:36:46.072
각 뉴런이 어떤 클래스에 연결되어 있는지에 따라
뉴런들이 서로 다른 loss를 가질 수는 있습니다.

00:36:46.072 --> 00:36:54.352
하지만 네트워크 전체를 보면 많은 뉴런들이 동일한 가중치로
연결되어 있을 것입니다.

00:36:54.352 --> 00:36:59.885
결국 모든 뉴런이 같은 방식으로 업데이트 될 것이고
이는 문제가 됩니다.

00:36:59.885 --> 00:37:10.885
우선 초기화 문제를 해결하는 첫번째 방법은
임의의 작은 값으로 초기화하는 것입니다.

00:37:10.885 --> 00:37:16.002
이 경우 초기 W를  표준정규분포(standard gaussian)
에서  샘플링합니다.

00:37:16.002 --> 00:37:22.450
좀 더 작은 값을 위해 스케일링을 해줍니다.
0.01을 나눠 표준편차를 1e-2 즉 0.01로 만들어 줍니다.

00:37:22.450 --> 00:37:25.640
이런 식으로 모든 가중치를 임의의 값으로 초기화합니다.

00:37:25.640 --> 00:37:30.729
여러분의 네트워크가 작은 네트워크라면
symmetry breaking에 뭐 이정도면 충분합니다.

00:37:30.729 --> 00:37:34.896
하지만 이 방법은 더 깊은 네트워크에서 문제가 생길 수 있습니다.

00:37:35.970 --> 00:37:43.070
그래서 이것이 왜 그런지 살펴 보겠습니다.
이런 식으로 실험을 해 볼 수 있습니다.

00:37:43.070 --> 00:37:45.341
조금 더 깊은 네트워크를 가지고 실험해봅시다.

00:37:45.341 --> 00:37:53.622
여기 10개의 레이어로 이루어진 네트워크가 있습니다.
레이어당 500개의 뉴런이 있습니다.

00:37:53.622 --> 00:37:56.437
nonlinearities로는 tanh를 사용해 봅시다

00:37:56.437 --> 00:38:06.116
그리고 가중치는 "임의의 작은 값" 으로 초기화시킵니다.

00:38:06.116 --> 00:38:12.356
데이터를 랜덤으로 만들어주고
이 데이터를 forward pass시켜보겠습니다.

00:38:12.356 --> 00:38:18.725
그리고 각 레이어별 activations 수치를 통계화 시켜보겠습니다.

00:38:22.476 --> 00:38:25.485
자 그럼 한번 분석을 해 보겠습니다. 가장 상단의 수치들은 글씨가
너무 작아서 잘 안보일 수도 있습니다.

00:38:25.485 --> 00:38:31.156
어쨋든 이 결과는 각 레이어 출력의 평균과
평균과 표준편차를 계산한 것입니다.

00:38:31.156 --> 00:38:39.410
우선 첫번째 레이어를 한번 봅시다.
평균은 항상 0 근처에 있습니다.(tanh 특성상)

00:38:40.267 --> 00:38:48.219
[마이크 잡음 관련]

00:38:49.613 --> 00:38:58.153
자 다시 여기 출력 분포들을 보면
당연하게도 평균은 항상 0 근처에 있습니다.

00:38:58.153 --> 00:39:01.175
여기 코드를 한번 봅시다.

00:39:01.175 --> 00:39:11.420
X와 W를 내적한 값에 tanh를 취합니다.
그리고 그 값을 저장합니다.

00:39:12.315 --> 00:39:16.780
tanh가 zero-centered 이니까 평균이
0에 가까운건 당연하겠죠

00:39:16.780 --> 00:39:22.450
하지만 표준편차를 보게되면 줄어듭니다.
아주 가파르게 줄어들어서 0에 수렴합니다.

00:39:22.450 --> 00:39:32.019
여기 가운데 그래프를 보시면 레이어당 평균과 표준편차를 나타낸 것입니다.

00:39:32.019 --> 00:39:38.592
그리고 맨 밑에 똑같은 결과를 분포로 표현했습니다.

00:39:38.592 --> 00:39:45.206
첫 번째 레이어에서는 가우시안스럽게 생긴
좋은 분포를 형성하고 있는것을 볼 수 있습니다.

00:39:45.206 --> 00:39:58.591
하지만 문제는 우리가 W를 곱하면 곱할수록
W가 너무 작은 값들이라서 출력 값이 급격히 줄어드는 것입니다.

00:39:58.591 --> 00:40:02.191
그리고 결국 0이 되겠죠

00:40:02.191 --> 00:40:04.262
우리가 원하는 것이 아닙니다.

00:40:04.262 --> 00:40:07.457
그래서 모든 활성함수 결과가 0이됩니다.

00:40:07.457 --> 00:40:10.420
자 그럼  backwards pass로 다시한번 생각해 봅시다.

00:40:10.420 --> 00:40:16.144
방금 전까지 한 것을 forward pass했다고 가정해보고
이제  gradient를 구해봅시다.

00:40:16.144 --> 00:40:20.024
우선 각 가중치들에 해당하는 gradient가 어떨 것이라고
다들 생각하십니까?

00:40:24.155 --> 00:40:26.238
정답 아는분 있으신가요?

00:40:28.571 --> 00:40:36.531
이렇게 생각해봅시다. 각 레이어의 "입력" 이 엄청 작은 것입니다.

00:40:36.531 --> 00:40:43.273
입력 값이 점점 0에 수렴합니다. Backporp을 생각해보면
"upstream gradient"가 점점 전파됩니다.

00:40:43.273 --> 00:40:53.483
자 그럼 현재 가중치를 업데이트하려면 "upstream gradient"
에 local gradient를 곱해주면 됩니다. 우선 WX를-

00:40:53.483 --> 00:40:56.985
W에 대해 미분해보면 local gradient는 입력 X가 됩니다.

00:40:56.985 --> 00:41:00.571
자 이렇게 생각해보면 앞서 다뤘던 문제와
유사한 문제가 생긴다는 것을 알 수 있습니다.

00:41:00.571 --> 00:41:07.058
X가 엄청 작은 값이기 때문에 gradient도 작을 것이고
결국 업데이트가 잘 일어나지 않습니다.

00:41:07.058 --> 00:41:13.488
이런 실험은 gradient의 흐름이 네트워크에 어떤 영향을
미치는지 생각해 볼 수 있는 좋은 예시입니다.

00:41:13.488 --> 00:41:20.329
이제는 forward pass의 형태를 살펴보고는 이런 경우 gradient가
어떤 식으로 전파되는지 짐작 하실 수 있을 것입니다.

00:41:20.329 --> 00:41:28.562
그리고 다양한 입력 타입에 따라 weight와 gradient가 어떤
영향을 미치는지도 생각해 볼 수 있겠습니다.

00:41:28.562 --> 00:41:38.025
그리고 또한 gradients가 연결되면서(chaining) 어떤 식으로
전파(flowing back)되는지를 한번 생각해본다면

00:41:40.004 --> 00:41:50.291
gradient를 backprop하는 과정은 그 반대입니다.
upstream gradient에 W의 gradient인 X를 곱합니다.

00:41:50.291 --> 00:41:53.085
그리고 입력 X은 어떤 내적(dot product)의 결과입니다.

00:41:53.085 --> 00:42:06.208
그리고 backward pass의 과정에서 upstream gradient를
구하는 것은 현재 upstream에 가중치를 곱하는 것 입니다.

00:42:07.283 --> 00:42:18.198
우리는 W를 계속해서 곱하기 때문에 Backwork pass에서도
Forward 처럼 점점 gradient값이 작아지게 됩니다.

00:42:18.198 --> 00:42:23.541
따라서 upstream gradients는 0으로 수렴하게됩니다.

00:42:23.541 --> 00:42:24.869
질문 있나요?

00:42:24.869 --> 00:42:28.452
[학생이 질문]

00:42:30.731 --> 00:42:37.945
예 물론 upstream과 downstream은 전혀 다른 것입니다.

00:42:37.945 --> 00:42:43.907
이 경우에는  backpropb를 하는 것이니 backward pass를
한다고 보시면 됩니다.

00:42:43.907 --> 00:42:51.409
upstream 은 gradient이 흘러간다고 보시면 됩니다.
loss에서부터 시작해서 최초 입력까지 흘러가죠

00:42:51.409 --> 00:42:58.684
upstream은 "우리가 이미 계산한 곳" 으로 부터 옵니다.
그리고 현재 노드를 계산하고 또 밑으로 내려가죠

00:43:00.270 --> 00:43:07.521
계속 아래로 흐른다고 보시면 됩니다. 그리고 backprop
으로 노트로 흘러 들어온 것이 upstream 입니다.

00:43:13.888 --> 00:43:21.102
 자 지금까지는 가중치가 엄청 작을 때 발생하는 문제를 살펴보았습니다.

00:43:21.102 --> 00:43:26.133
그렇다면 가중치를 좀 더 큰 값으로 초기화하면 어떨지
한번 생각해 볼 수 있을 것입니다.

00:43:26.133 --> 00:43:38.273
자 그럼 가중치의 편차를 0.01 이 아니라 1로 하면
어떻게 될까요?

00:43:44.558 --> 00:43:54.750
자 이제 가중치가 큽니다. 이렇게 큰 가중치를 통과한 출력
WX를 구하고 이를 tanh를 거치게 된다면 어떨까요?

00:43:54.750 --> 00:44:01.883
앞서 tanh의 입력에 따라 어떤 일이 발생하는지 배웠습니다.
그렇다면 문제가 뭘까요?

00:44:01.883 --> 00:44:06.289
맞습니다. 값들이 saturation 될 것입니다.

00:44:06.289 --> 00:44:15.966
가중치가 큰 값을 가지므로 tanh의 출력은
항상 saturation될 것입니다.

00:44:15.966 --> 00:44:29.695
그렇게 되면 다음과 같은 결과를 확인 해 볼 수 있는데.
출력이 항상 -1 이거나 +1 일 것입니다.

00:44:30.855 --> 00:44:40.447
앞서 말했듯 값이 saturation 될 것이고 gradient는
0이 될 것입니다. 가중치 업데이트가 일어나지 않겠죠.

00:44:41.397 --> 00:44:46.363
결국 적절한 가중치를 얻기는 너무 어렵습니다.

00:44:46.363 --> 00:44:50.296
너무 작으면 사라져버리고
너무 크면 saturation되어 버립니다

00:44:50.296 --> 00:44:55.553
그래서 사람들이 어떻게 하면 가중치 초기화를 잘 할 수 있을까
하고 열심히 고민하였습니다.

00:44:55.553 --> 00:45:02.507
널리 알려진 좋은 방법 중 하나는 바로
Xavier initialization 입니다.

00:45:02.507 --> 00:45:07.388
Glorot가 2010에 발표한 논문입니다.

00:45:07.388 --> 00:45:15.962
자 그럼 맨 위에 W의 공식을 한번 보겠습니다.

00:45:17.403 --> 00:45:22.653
Standard gaussian으로 뽑은 값을
"입력의 수" 로 스케일링해줍니다.

00:45:22.653 --> 00:45:28.599
웹에 에된 Lecture note를 보시면 상세한 수식을
확인 해 보실 수 있습니다.

00:45:28.599 --> 00:45:35.789
기본적으로 Xavier initialization가 하는 일은 입/출력의
분산을 맞춰주는 것입니다.

00:45:35.789 --> 00:45:42.789
그리고 이 수식을 통해서 직관적으로 이해할 수 있는 것은

00:45:42.789 --> 00:45:52.654
입력의 수가 작으면 더 작은 값으로 나누고 좀 더 큰 값을 얻습니다.
그리고 우리는 더 큰 가중치가 필요합니다. 왜냐하면-

00:45:52.654 --> 00:45:58.993
작은 입력의 수가 가중치와 곱해지기 때문에, 가중치가 더
커야만 출력의 분산 만큼 큰 값을 얻을 수 있기 때문입니다.

00:45:58.993 --> 00:46:08.505
반대로 입력의 수가 많은 경우에는 더 작은 가중치가 필요합니다.

00:46:08.505 --> 00:46:10.795
더 자세한 내용은 Lecture Note를 참고하시기 바랍니다.

00:46:10.795 --> 00:46:23.150
각 레이어의 입력이 Unit gaussian이길 원한다면 이런 류의
초기화 기법을 사용해 보실 수 있습니다.

00:46:23.150 --> 00:46:27.669
각 레이어의 입력을 Unit gaussian스럽게(approximately)
만들어 줄 수 있습니다.

00:46:29.057 --> 00:46:35.032
여기서 가정하는 것은 현재
Linear activation이 있다고 가정하는 것입니다.

00:46:35.032 --> 00:46:40.837
가령 tanh의 경우 우리가 지금 tanh의 active region안에
있다고 가정하는 것입니다.

00:46:40.837 --> 00:46:46.051
다시 한번 말씀드리지만 lecture note를 보시면
좀 더 자세한 이해를 하실 수 있을 것입니다.

00:46:46.051 --> 00:46:51.255
하지만 문제가 하나 있습니다.
ReLU를 쓰면 잘 동작하지 않는다는 것입니다.

00:46:51.255 --> 00:46:54.849
ReLU를 쓰면 무슨 일이 일어나는지를 보면

00:46:54.849 --> 00:47:04.685
ReLU는 출력의 절반을 죽입니다. 그 절반은 매번 0이 됩니다.
그래서 결국 출력의 분산을 반토막 내버립니다.

00:47:04.685 --> 00:47:16.193
그러므로 이전과 같은 가정을 해버리면 ReLU에서는 잘 작동하지 않습니다.
값이 너무 작아지는 것입니다.

00:47:16.193 --> 00:47:23.323
여기 보이는 것이 그런 현상인데
분포가 또 줄어들기 시작했습니다.

00:47:23.323 --> 00:47:28.019
점점 더 많은 값들이 0이 되고
결국은 비활성(deactivated) 되버립니다.

00:47:29.541 --> 00:47:41.580
이 문제를 해결하기 위한 일부 논문이 있는데
여기에서는 추가적으로 2를 더 나눠줍니다.

00:47:41.580 --> 00:47:47.023
뉴런 들 중 절반이 없어진다는 사실을 고려하기 위해서 입니다.

00:47:48.636 --> 00:47:58.122
일제 입력은 반밖에 안들어가므로 반으로 나눠주는 텀을
추가적으로 더해 주는 것이고 실제로 잘 동작합니다.

00:47:59.332 --> 00:48:05.348
결과를 보시면 전체적으로 좋은 분포를 형성하고
있는것을 볼 수 있습니다.

00:48:06.959 --> 00:48:16.161
실제로 이 작은 변화는 트레이닝에 있어서 엄청난 차이를 보입니다.

00:48:16.161 --> 00:48:28.309
가령 일부 논문을 보면 그런 차이가 트레이닝이 정말 잘 되거나
하나도 안되거나를 결정하는 결과를 보이기도 합니다.

00:48:32.548 --> 00:48:36.321
적절한 초기화는 여전히 활발이 연구되는 분야입니다.

00:48:36.321 --> 00:48:40.281
관심 있는 분들은 이 논문과 리소스를 활용하시면 될 것입니다.

00:48:40.281 --> 00:48:51.701
초기화는 우선 Xavier Initialization을 추천드리며
그 밖에 다른 방법을 시도해 보는 것도 좋을 것입니다.

00:48:53.871 --> 00:49:01.405
gaussian의 범위로 activation을 유지시키는 것에 관련한
또 다른 아이디어를 하나 소개해 드리겠습니다.

00:49:03.330 --> 00:49:09.672
우리는 레이어의 출력이 unit gaussian 이길 바랍니다.
Batch normalization이라 불리는 이 아이디어는 -

00:49:09.672 --> 00:49:14.240
그렇다면 그렇게 만들어보자 하는 것입니다.
그냥 강제로 그렇게 만들어보자

00:49:14.240 --> 00:49:15.834
그럼 이것이 어떻게 동작할까요?

00:49:15.834 --> 00:49:25.640
어떤 레이어로부터 나온 Batch 단위 만큼의 activations 이 있다고
했을때, 우린 이 값들이 Unit gaussian 이기를 원합니다.

00:49:25.640 --> 00:49:29.368
누구나 이 데이터를 Unit Gaussian으로
(empirically) 만들 수 있습니다.

00:49:29.368 --> 00:49:39.392
현재 Batch에서 계산한 mean과 variance를 이용해서
Normalization 해 볼 수 있을 것입니다.

00:49:39.392 --> 00:49:50.867
가중치를 잘 초기화 시키는 것 대신에 학습 할 때 마다 각 레이어에
이런 일을 해줘서 모든 레이어가 Unit gaussian이 되도록 해줍니다.

00:49:50.867 --> 00:49:53.096
그래서 결국 학습하는 동안 모든 레이어의 입력이
Unit gaussian이 됐으면 좋겠는 것입니다.

00:49:53.096 --> 00:49:58.336
그래서 이제부터 할 일은 네트워크의 forward pass 동안에
그렇게 되도록 "명시적으로"  만들어 주는 것입니다.

00:49:58.336 --> 00:50:06.787
각 뉴런을 평균과 분산으로 Normalization 해주므로서
이런 일을 함수로(functionally) 구현하는 것입니다.

00:50:08.139 --> 00:50:15.754
Batch단위로 한 레이어에 입력으로 들어오는 모든 값들을 이용해서
평균과 분산을 구해서 Normalization 해주는 것입니다.

00:50:15.754 --> 00:50:19.928
그리고 이런게 만큼 함수를 보면
미분 가능한 함수입니다.

00:50:19.928 --> 00:50:31.098
평균과 분산을 "상수" 로 가지고만 있으면 언제든지 미분이
가능하며 따라서 Backprop이 가능하게 됩니다.

00:50:33.115 --> 00:50:47.065
여기 보시면 Batch당 N개의 학습 데이터가 있고
각 데이터가 D차원이라고 해봅시다.

00:50:47.065 --> 00:50:56.063
그리고 각 차원별로(feature element별로) 평균을 각각 구해줍니다.

00:50:56.063 --> 00:51:02.406
한 Batch 내에 이걸 전부 계산해서 Normalize 합니다.

00:51:05.786 --> 00:51:09.988
그리고 이 연산은 FC나 Cov Layer 직후에 넣어줍니다.

00:51:09.988 --> 00:51:18.932
깊은 네트워크에서 각 레이어의 W가 지속적으로 곱해져서
Bad scaling effect가 발생했습니다만

00:51:18.932 --> 00:51:22.731
Normalization은 그 bad effect를 상쇄시켜 버립니다.

00:51:22.731 --> 00:51:37.132
BN은 입력의 스케일만 살짝 조정해 주는 역할이기 때문에
FC와  Conv 어디에든 적용할 수 있습니다.

00:51:37.132 --> 00:51:45.895
Conv Layer에서 차이점이 있다면 Normalization을 차원마다
독립적으로 수행하는 것이 아니라

00:51:45.895 --> 00:51:58.895
같은 Activation Map의 같은 채널에 있는 요소들은 같이
Normalize 해 줍니다.

00:51:58.895 --> 00:52:05.903
왜냐하면 Conv 특성상 (convolutional property)
같은 방식으로 normalize 시켜야 하기 때문입니다.

00:52:05.903 --> 00:52:13.489
Conv Layer의 경우 Activation map(채널, Depth)
마다 평균과 분산을 하나만 구합니다.

00:52:13.489 --> 00:52:18.094
그리고 현재 Batch 에 있는 모든 데이터로 Normalize 해줍니다.

00:52:18.094 --> 00:52:23.098
Batch Normalization는 숙제로 나갈 것입니다.

00:52:23.098 --> 00:52:29.367
Batch Normalization 2015년도 논문에
더 자세하게 설명이 되어 있습니다.

00:52:29.367 --> 00:52:35.621
Batch Normalization 은 아주 유용한 기법이고
실제로 정말 많이 사용하는 방법입니다.

00:52:35.621 --> 00:52:46.129
BN을 사용하려면 논문을 읽어보셔야 합니다.
BN의 흐름도 한번 살펴보시고

00:52:46.129 --> 00:52:53.718
BN에서 Gradient를 어떻게 구하는 지도
한번 살펴보시길 바랍니다.

00:52:56.626 --> 00:52:59.993
그런데 한가지 문제가 있습니다.

00:52:59.993 --> 00:53:05.930
FC layer를 거칠 때 마다 매번 normalization를
해주는 것에 대한 의문이 있습니다.

00:53:05.930 --> 00:53:12.031
우리가 정말 tanh의 입력이 unit gaussian
이기를 바라는 것일까요?

00:53:12.031 --> 00:53:17.107
normalization이 하는 일은 입력이 tanh의 linear한 영역에만
존재하도록 강제하는 것입니다.

00:53:17.107 --> 00:53:21.974
그렇게 되면 saturation이 전혀 일어나지 않게 됩니다.

00:53:21.974 --> 00:53:30.821
saturation 이 전혀 일어나지 않는것 보다는 "얼마나"
saturation이 일어날지를 우리가 조절하면 더 좋겠죠

00:53:31.845 --> 00:53:39.512
Batch normalization에서는 normalization연산이 있었죠
(왼쪽 상단 Narmalize: 수식)

00:53:39.512 --> 00:53:44.453
그 이후에 BN에서는 scaling 연산을 추가합니다.

00:53:44.453 --> 00:53:52.515
이를 통해 Unit gaussian으로 normalize 된 값들을
감마로는 스케일링의 효과를, 베타는 이동의 효과를 줍니다.

00:53:53.349 --> 00:54:02.071
이렇게 하면 normalized 된 값들을 다시 원상복구
할 수 있도록 해줍니다. 그렇게 하고 싶다면 말이죠

00:54:02.071 --> 00:54:10.613
네트워크가 값 들을 원상복구 하고 싶다면
"감마 = 분산", "베타 = 평균" 로 하면 됩니다.

00:54:10.613 --> 00:54:16.659
 BN을 하기 전 값으로 돌아가는 것입니다.

00:54:16.659 --> 00:54:32.225
네트워크가 데이터를 tanh에 얼마나 saturation 시킬지를 학습
하기 때문에 우리는 유연성을 얻을 수 있습니다.

00:54:38.166 --> 00:54:42.285
 Batch normalization를 다시한번 요약해 보자면

00:54:42.285 --> 00:54:52.906
입력이 있고 우리는 mini-batch에서의 평균을 계산합니다. 모든
mini-batch 마다 각각 계산해 줍니다. 분산도 계산합니다.

00:54:52.906 --> 00:54:58.342
그리고 평균과 분산으로 Normalize 한 이후에
다시 추가적인 scaling, shifting factor를 사용합니다.

00:54:58.342 --> 00:55:05.484
BN은 gradient의 흐름을 보다 원활하게 해주며
결국 더 학습이 더 잘되게(robust) 해줍니다.

00:55:05.484 --> 00:55:10.562
BN을 쓰면 learning rates를 더 키울 수도 있고 다양한
초기화 기법들도 사용해 볼 수 있습니다.

00:55:10.562 --> 00:55:16.955
그래서 사람들이 BN을 쓰면 학습이 더 쉬워진다고 합니다.
BN를 써야하는 이유죠.

00:55:16.955 --> 00:55:27.162
그리고 또 하나 짚고 넘어가야 할 것은 BN이
regularization의 역할도 한다는 것입니다.

00:55:27.162 --> 00:55:42.733
각 레이어의 출력은 해당 데이터 하나 뿐만 아니라 batch 안에
존재하는 모든 데이터들에 영향을 받습니다.(평균, 분산)

00:55:42.733 --> 00:55:48.266
왜냐하면 각 레이어의 입력은 해당 배치의
(표본)평균으로 Normalize 되기 때문입니다.

00:55:48.266 --> 00:55:54.021
그렇기 때문에 이 레이어의 출력은 이제 오직 하나의 샘플에
대한 deterministic한 값이 아니게 되고

00:55:54.021 --> 00:55:57.543
Batch 내의 모든 데이터가 입력으로 한대 묶인다고 볼 수 있습니다.

00:55:57.543 --> 00:56:07.215
그러므로 더 이상 레이어의 출력은 deterministic하지 않고
조금씩 바뀌게 되고 이는 regularization effect를 줍니다.

00:56:08.941 --> 00:56:10.490
질문있나요?

00:56:10.490 --> 00:56:13.401
[학생이 질문]

00:56:13.401 --> 00:56:17.354
질문은 감마와 베타가 학습가능한 파라미터 냐는 것인데
예 맞습니다.

00:56:17.354 --> 00:56:20.937
[학생이 질문]

00:56:27.754 --> 00:56:34.618
질문은 바로 왜 감마와 베타를 학습시켜서 다시
 identity function(Y = X)가 되게 하는 것인지 압니다.

00:56:34.618 --> 00:56:38.481
이렇게 하는 이유는 유연성을 위해서 입니다.

00:56:38.481 --> 00:56:48.381
 batch normalization이 하는 일을 생각해보면 레이어의 입력이
unit gaussian이 되도록 강제하는 것입니다.

00:56:48.381 --> 00:56:54.232
일반적으로 이렇게 Normalize 하는 것이 좋긴 하지만
그렇다고 항상 좋은 것은 아닙니다.

00:56:54.232 --> 00:57:00.279
tanh의 예시에서도 보았듯이 여러분은 입력데이터가 tanh로
인해 얼마나 saturation 될지를 조절하고 싶을 수도있습니다.

00:57:00.279 --> 00:57:14.195
이런 유연성을 통해서 gaussian normalization이 필요하면
그렇게 해주고 또 일부 그 방법이 최선이 아닐때가 있으면 -

00:57:14.195 --> 00:57:19.838
unit gaussian을 조금씩 조금씩 scaling 하고 shifting
할 수 있는 여지를 주는 것입니다.

00:57:19.838 --> 00:57:25.968
감마와 베타라는 파라미터는 이런 추가적인
유연성을 제공해 줍니다.

00:57:25.968 --> 00:57:35.665
때문에  batch 단위로 normalization을 일단 해주고
파라미터를 다시 학습시키는 것입니다.

00:57:35.665 --> 00:57:39.710
[학생이 질문]

00:57:39.710 --> 00:57:47.079
예 맞습니다. 각 뉴런의 출력입니다. 가령 FC Layer의
출력으로 Wx가 있다고 해보면

00:57:48.366 --> 00:57:57.365
출력으로 나온  각 뉴런마다 각각 batch normalization을
적용하는 것입니다.

00:57:57.365 --> 00:57:58.835
질문 있나요?

00:57:58.835 --> 00:58:02.418
[학생이 질문]

00:58:10.031 --> 00:58:17.517
질문은 바로 reinforcement learning와 같이 batch
사이즈가 작은 경우 어떻게 해야 하는지 입니다.

00:58:17.517 --> 00:58:24.324
실제로 BN은 일반적인 CNN에 정말 널리 쓰이고 있습니다.

00:58:24.324 --> 00:58:34.520
그리고 recurrent / reinforcement learning 등
다양한 네트워크에 어떻게 적용하는지에 대한 많은 논문들이 있습니다.

00:58:34.520 --> 00:58:40.532
이런 네트워크에는 또 다른 고려사항이 있겠죠.
현재도 아주 활발에 연구되는 분야입니다.

00:58:40.532 --> 00:58:49.490
일부 논문은 나중에 살펴볼 예정이지만 대부분의 CNN에서
BN은 아주 잘 동작합니다.

00:58:49.490 --> 00:58:57.741
Batch 사이즈가 작으면 정확도가 떨어지긴 하겠지만
여전히 비슷한 효과를 주긴 합니다.

00:58:57.741 --> 00:59:06.088
Batch 사이즈가 작은 경우 더 많은 샘플들을 이용해서 평균과 분산을
구할 수 있도록 다시 디자인하는 방법도 있을 것입니다.

00:59:06.088 --> 00:59:14.755
실제로는 이런 경우가 흔하지는 않습니다. 하지만 Batch가
작아서 문제가 될 때 도움을 줄 수는 있을 것입니다.

00:59:14.755 --> 00:59:16.128
질문 있나요?

00:59:16.128 --> 00:59:19.711
[학생이 질문]

00:59:24.947 --> 00:59:32.979
질문은 바로 우리가 입력을 gaussian 이라고 강제해 버리면
기존의 구조(structure)를 잃는 것 아닌지 입니다.

00:59:35.211 --> 00:59:45.221
우선은 아닙니다. 데이터의 전처리를 할때도 gaussian을 쓰죠
모든 입력들(features) 가우시안 분포로 만든다고 해도 -

00:59:45.221 --> 00:59:47.925
어떠한 구조도 잃지 않습니다.

00:59:47.925 --> 00:59:57.913
데이터에 "연산이 잘 수행되도록"  우리는 그저 데이터를 조금만
움직이고 스케일링 하는 것입니다. (선형변환임)

00:59:57.913 --> 01:00:03.169
CNN을 보면 우리는 데이터의 "공간적인 구조" 가
잘 유지되길 바랍니다.

01:00:03.169 --> 01:00:09.156
Conv Layer 출력인 activation maps이 그런
"공간적 구조" 를 유지하고 있기를 원합니다.

01:00:09.156 --> 01:00:17.823
이 점을 고려해서 CNN Activation Map을
normalize할 때는 전체 map의 평균과 분산을 같이 구합니다.

01:00:17.823 --> 01:00:22.815
Activation Map 당 평균과 분산을 하나씩만 구하는 것입니다.

01:00:22.815 --> 01:00:32.455
이와 관련된 사항은 BN 논문에도 잘 설명되어 있으며
여러분이 과제로도 해야 할 것입니다.

01:00:32.455 --> 01:00:33.288
질문 있나요?

01:00:34.287 --> 01:00:37.870
[학생이 질문]

01:00:43.065 --> 01:00:47.849
질문은 우리가 "레이어의 가중치"를 Normalize 하는 이유
가 gaussian으로 만들기 위해서 인지 입니다.

01:00:47.849 --> 01:00:49.665
질문을 좀 정정하자면 "레이어의 가중치" 가 아니라
"레이어의 입력" 이죠

01:00:49.665 --> 01:00:58.727
우선 "레이어의 가중치" 가 아니라
"레이어의 입력"을 Normalize하는 것입니다.

01:01:00.895 --> 01:01:04.562
[학생이 질문]

01:01:15.208 --> 01:01:24.512
질문은 "레이어의 입력"에 평균을 빼고 표준편차로 나눠주면
gaussian이 되냐는 것입니다. 예 맞습니다.

01:01:24.512 --> 01:01:33.843
Normalize 를 할때 데이터에 어떤 일이 발생하는지 한번 생각해봅시다.
우선 mean 만큼 이동하죠 그러면 zero-centered가 될 것입니다.

01:01:33.843 --> 01:01:40.243
그리고 표준편차로 스케일링합니다.
이 과정을 거치면 Unit gaussian으로 변환되는 것입니다.

01:01:41.249 --> 01:01:48.630
이에 대한 자세한 내용은 기계학습을 설명하는 많은
자료들이 있으니 찾아보시기 바랍니다.

01:01:48.630 --> 01:01:52.942
실제로 어떤 일이 일어나는지를 시각화한 자료도 있습니다.

01:01:52.942 --> 01:01:58.563
하지만 기본적으로 normalize 가 하는 일은 여러분의 데이터를
gaussian distribution으로 만들어 주는 것입니다.

01:02:00.458 --> 01:02:02.375
질문있나요?

01:02:03.436 --> 01:02:07.019
[학생이 질문]

01:02:08.262 --> 01:02:09.095
어 허.

01:02:26.194 --> 01:02:35.634
질문은 shift와 scale요소를 추가시키고 학습을 시켜버리면
결국 identity mapping이 되서 BM이 사라지는 것 아닌지 입니다.

01:02:35.634 --> 01:02:44.523
네트워크가 BM이 쓸모없다고 판단해서 identity mapping으로
만들어 버린다면 물론 그렇게 되겠지요

01:02:44.523 --> 01:02:52.579
하지만 실제로는 그런 일은 일어나지 않습니다. 실제로 감마와
베타를 학습시키게 되면 identity 가 되지는 않습니다.

01:02:52.579 --> 01:02:58.858
shift와 scale이 일정량 변하긴 하지만 보통은
dentity mapping이 될 정도는 아닙니다.

01:02:58.858 --> 01:03:03.201
때문에 여전히 batch normalization의 효과를 얻을 수 있습니다.

01:03:03.201 --> 01:03:14.266
수업자료에 identity mapping를 넣은 이유는 극단의 경우에
가능하다는 것이지 실제로는 일어나지 않습니다.

01:03:14.266 --> 01:03:15.970
질문있나요?

01:03:15.970 --> 01:03:19.553
[학생이 질문]

01:03:21.368 --> 01:03:22.561
[학생이 질문]

01:03:22.561 --> 01:03:26.144
[학생이 질문]

01:03:30.825 --> 01:03:37.505
질문을 잘 이해한 것인지 모르겠지만 이전에 있었던
질문과도 상당히 유사한 것 같네요

01:03:38.972 --> 01:03:49.814
우리가 지금 하는 일은 unit gaussian으로 맞춰주는 것이죠 그렇다고
실제 데이터가 gaussian이 되는 것은 아닙니다.

01:03:49.814 --> 01:03:57.830
입력 데이터가 당연히 완전한 gaussian 분포일 수는 없겠죠
다만 gaussian과 비슷하다(approximately)고 가정하고나서 -

01:03:57.830 --> 01:04:03.592
BM이 잘 동작하기를 기대하는 것입니다.
실제로 입력이 Gaussian을 따르지는 않습니다.

01:04:06.658 --> 01:04:14.017
자  batch normalization에 대해 마지막으로 말씀드릴 것은
Test time에서 어떻게 동작하는지 입니다.

01:04:17.064 --> 01:04:26.932
BM에서 평균과 분산은 학습데이터에서 구한 것입니다.
Test time에 추가적인 계산은 하지 않습니다.

01:04:26.932 --> 01:04:38.295
Training time에 running averages 같은 방법으로 평균
분산을 계산하고 Test time에 사용합니다.

01:04:40.078 --> 01:04:43.725
자 이제 학습과정을 다루는법에 대해 알아보겠습니다.

01:04:43.725 --> 01:04:54.264
지금까지 네트워크 설계를 배웠습니다. 이제는 학습과정을 어떻게
모니터링하고 하이퍼파라미터를 조절할 것인지를 배워보겠습니다.

01:04:54.264 --> 01:04:56.681
좋은 학습 결과를 얻기 위해서 말이죠

01:04:58.091 --> 01:05:02.251
우선 가장 첫 단계는 데이터 전처리입니다.

01:05:02.251 --> 01:05:05.773
앞서 배운것 처럼 zero-mean을 사용합니다.

01:05:05.773 --> 01:05:13.455
그리고 아키텍쳐를 선택해야합니다. 우선 하나의 Hidden Layer
와 50개의 뉴런을 가진 모델로 해봅시다.

01:05:13.455 --> 01:05:18.950
그 밖에 어떤 모델을 선택해도 상관없습니다.

01:05:20.223 --> 01:05:23.934
이제 해야할 일은 네트워크를 초기화시키는 것입니다.

01:05:23.934 --> 01:05:28.600
Forward pass를 하고난 후에 Loss가 그럴듯해야 합니다.

01:05:28.600 --> 01:05:35.697
지난 강의에서 배웠듯이
가령 우리가 softmax를 사용하고자 한다면

01:05:37.493 --> 01:05:44.012
우리는 가중치가 작은 값일 때 Loss가 대강 어떻게
분포해야 하는지를 이미 알고있습니다.

01:05:44.012 --> 01:05:50.293
Softmax classifier의 Loss는
negative log likelihood 가 되어야 합니다.

01:05:50.293 --> 01:05:54.826
가령 10개의 클래스라면 Loss는
-log(1/10) 이 될 것입니다.

01:05:54.826 --> 01:06:03.213
여기 보시면 약 2.3 정도 되는 것을 보실 수 있습니다.
이를 통해 Loss가 원하는 대로 동작한다는 것을 알 수 있습니다.

01:06:03.213 --> 01:06:09.453
이 방법은 언제든 사용할 수 있는 유용한 방법입니다.
(Good sanity check)

01:06:09.453 --> 01:06:13.503
자 그럼 초기 Loss가 정상이라는 것을 확인했다면

01:06:14.853 --> 01:06:25.463
지금까지는 여기 regularization을 0으로 설정하였습니다.
앞서 계산한 2.3은 regularization을 사용하지 않은 상태입니다.

01:06:25.463 --> 01:06:36.226
여기에 regularization을 추가하면 Loss가 증가합니다.
손실함수에 regularization term이 추가되기 때문입니다.

01:06:36.226 --> 01:06:40.879
이 또한 유용한 sanity check입니다.

01:06:40.879 --> 01:06:46.309
자 이제 학습을 진행할 준비가 끝났습니다.
이제 학습을 한번 시작해봅시다.

01:06:47.331 --> 01:06:53.026
처음 시작할 때 좋은 방법은 데이터의 일부만 우선
학습시켜 보는 것입니다.

01:06:53.026 --> 01:07:00.944
데이터가 적으면 당연히 Overfit이 생길 것이고
Loss가 많이 줄어들 것입니다.

01:07:00.944 --> 01:07:10.697
이때는 regularization를 사용하지 않습니다.
그리고 Loss가 내려가는지를 확인하는 것입니다.

01:07:12.199 --> 01:07:21.961
여기 처럼 Epoch마다 Loss가 잘 내려가는지를 보는 것입니다.
Loss가 0을 향해 꾸준히 잘 내려가는지를 확인해 봅니다.

01:07:21.961 --> 01:07:27.124
Loss가 내려감과 동시에 Train Accuracy는 점점 증가합니다.
당연하겠죠

01:07:27.124 --> 01:07:32.813
데이터가 작은 경우라면 모델이 완벽하게
데이터를 overfit 할 수 있어야 합니다.

01:07:34.726 --> 01:07:40.366
자 지금까지의 sanity checks가 잘 끝났다면
이제부터는 정말로 학습을 시작할 차례입니다.

01:07:40.366 --> 01:07:49.480
이제는 전체 데이터 셋을 사용할 것이고 regularization
을 약간만 주면서 적절한  learning rate를 찾아야 합니다.

01:07:49.480 --> 01:07:54.942
Learning rate는 가장 중요한 하이퍼파라미터 중 하나입니다.
가장 먼저 정해야만 하는 하이퍼파라미터 입니다.

01:07:54.942 --> 01:08:00.954
우선 learning rate 몇 가지를 정하고 실험해 봅니다.
여기에서는 1e- 6으로 정해 봤습니다.

01:08:00.954 --> 01:08:04.096
그 결과로는 loss가 좀처럼 변하지 않는 것을 알 수 있습니다.

01:08:04.096 --> 01:08:10.244
Loss가 잘 줄어들지 않는 가장 큰 요인은
Learning rate가 지나치게 작은 경우입니다.

01:08:10.244 --> 01:08:16.362
Learning rate가 지나치게 작으면 gradient 업데이트가
충분히 일어나지 않게 되고 cost가 안변하게 됩니다.

01:08:17.423 --> 01:08:29.806
여기에서 유심히 살펴봐야 할 점은 loss가 잘 변하지 않음에도
training/validation accuracy가 20%까지 급상승합니다.

01:08:32.701 --> 01:08:38.152
혹시 왜 이런지 대답해 줄 분 계신가요?

01:08:40.089 --> 01:08:46.403
현재 Softmax를 사용하고 있고 loss가 크게 안변했음에도
Accuracy는 올라간 상태입니다.

01:08:50.263 --> 01:08:59.727
현재 상황은 확률 값들이 아직까지 멀리 퍼져있고
때문에  loss는 여전히 비슷비슷한 것입니다.

01:08:59.727 --> 01:09:06.183
하지만 이 확률은 조금씩 "옮은" 방향으로 바뀌고 있습니다.
우리가 지금 "학습" 을 하고 있기 때문이죠

01:09:06.183 --> 01:09:11.954
가중치는 서서히 변하고 있지만
Accuracy는 갑자기 뛰어버릴 수 있습니다.

01:09:11.954 --> 01:09:21.985
Accuracy는 그저 가장 큰 값만 취하기 때문에
Accuracy가 크게 뛸 수 있는 것입니다.

01:09:23.588 --> 01:09:31.325
자 이제 learning rate를 좀 바꿔봅시다. 더 큰 값인
1e-6를 1e6로 한번 바꿔보겠습니다.

01:09:31.326 --> 01:09:41.413
자 결과를 보면 cost가 NaNs임을 알 수 있습니다.
NaNs이라는 것은 cost가 발산(exploded)한 것입니다.

01:09:41.413 --> 01:09:47.862
주된 이유는 learning rate가 지나치게 높기 때문입니다.

01:09:49.350 --> 01:09:57.006
이 경우에는 learning rate를 낮춰야만 합니다. 그래서
3e-3으로 했는데, 여전히 발산합니다.

01:09:57.006 --> 01:10:04.901
보통 learning rate는 1e-3 에서 1e-5
사이의 값을 사용합니다.

01:10:04.901 --> 01:10:09.628
이 범위 사이의 값을 이용해서 cross-validation 을
수행해 줍니다.

01:10:09.628 --> 01:10:19.011
이 사이의 값들을 이용해서 learning rate가 지나치게 작은지
아니면 큰지를 결정할 수 있을 것입니다.

01:10:21.228 --> 01:10:24.399
자 그럼 하이퍼파라미터는 어떻게 정해줘야 할까요

01:10:24.399 --> 01:10:31.139
하이퍼 파라미터를 최적화시키고 그중 가장 좋은 것을
선택하려면 어떻게 해야 할까요?

01:10:31.139 --> 01:10:37.575
취할 수 있는 한가지 전략은 바로 cross-validation 입니다.

01:10:37.575 --> 01:10:43.472
Cross-validation은 Training set으로 학습시키고
Validation set으로 평가하는 방법입니다.

01:10:43.472 --> 01:10:48.960
이 hyperparameter가 잘 동작하는지를 확인해봅니다.
아마 과제에 있어서 이미 해보신 분도 계실 것입니다.

01:10:48.960 --> 01:10:51.334
hyperparameter를 좀 더 단계적으로 찾아봅시다.

01:10:51.334 --> 01:11:03.473
우선 coarse stage 에서는 넓은 범위에서 값을 골라냅니다.
Epoch 몇 번 만으로도 현재 값이 잘 동작하는지 알 수 있습니다.

01:11:03.473 --> 01:11:07.993
Epoch이 많지 않아도 어떤 하이퍼파라미터가
좋은지 아닌지를 알 수 있습니다.

01:11:07.993 --> 01:11:13.712
Nan이 뜨거나 혹은 Loss가 줄지 않거나 하는 것을 보면서
이에 따라 적절히 잘 조절할 수 있을 것입니다.

01:11:13.712 --> 01:11:22.540
coarse stage가 끝나면 어느 범위에서 잘 동작하겠다를
대충 알게 될 것입니다.

01:11:22.540 --> 01:11:30.779
두 번째 fine stage에서는 좀 더 좁은 범위를 설정하고
학습을 좀 더 길게 시켜보면서 최적의 값을 찾습니다.

01:11:30.779 --> 01:11:47.296
NaNs 으로 발산하는 징조를 미리 감지할 수도 있습니다.
Train 동안에 Cost가 어떻게 변하는 지를 살펴보는 것입니다.

01:11:47.296 --> 01:11:57.902
이전의 cost보다 더 커지거나 한다면, 가령 이전보다 cost가
3배 높아졌다거나 하면 잘못 하고 있는 것입니다.

01:11:57.902 --> 01:12:06.335
Cost가 엄청 크고 빠르게 오르고 있다면 loop를 멈춰버리고
다른 하이퍼파라미터를 선택하면 됩니다.

01:12:06.335 --> 01:12:12.496
자 예시를 한번 보겠습니다. 이는 5 epochs을 돌며
coarse search를 하는 과정입니다.

01:12:13.866 --> 01:12:24.611
네트워크 구조는 앞서 만든 것과 유사합니다.
여기에서 확인 해야 할 것은 validation accuracy 입니다.

01:12:24.611 --> 01:12:29.291
높은 val_acc에는 빨간색으로 표시를 해 놨습니다.

01:12:29.291 --> 01:12:33.092
빨간 색으로 표시해 둔 지역이 바로
fine-stage를 시작할 만한 범위가 될 것입니다.

01:12:33.092 --> 01:12:37.067
한 가지 주목할 점은 하이퍼 파라미터 최적화 시에는
 Log scale로 값을 주는 것이 좋습니다.

01:12:37.067 --> 01:12:49.040
파라미터 값을 샘플링할때 10^-3 ~ 10^-6 을 샘플링하지 말고
10의 차수 값만 샘플링하는 것이 좋습니다.(-3 ~ -6)

01:12:49.956 --> 01:12:55.427
왜냐하면 learning rate는 gradient와 곱해지기 때문에

01:12:55.427 --> 01:13:07.524
 learning rate의 선택 범위를 log scale을
사용하는 편이 좋습니다.

01:13:07.524 --> 01:13:10.894
따라서 차수(orders of magnitude)을 이용하는 편이 좋습니다.

01:13:10.894 --> 01:13:14.379
자 그럼 범위를 다시한번 조절해 보겠습니다 (오른쪽)

01:13:14.379 --> 01:13:26.176
reg는 경우를 보면 범위를 10^-4 에서 10^0 정도로
좁히면 좋을 것 같습니다. 나쁘지 않은 방법입니다.

01:13:26.176 --> 01:13:37.962
이쪽 범위에서 53%의 val_acc를 보이는 것을 알 수 있습니다.
학습이 가장 잘 되는 구간이 될 것입니다.

01:13:37.962 --> 01:13:42.377
하지만 여기에는 문제가 하나 있습니다.

01:13:42.377 --> 01:13:50.396
자 우리는 여기에서 가장 좋은 Accuracy를 찾았습니다. (화살표)

01:13:52.373 --> 01:13:57.816
잘 보면 good learning rates는 전부
10E-4 사이에 존재하고 있습니다.

01:13:57.816 --> 01:14:10.273
Learning rate의 최적 값들이 우리가 다시 좁혀 설정한
범위의 경계부분에 집중되어 있다는 것을 알 수 있습니다.

01:14:10.273 --> 01:14:11.856
이것은 좋지 않죠

01:14:12.693 --> 01:14:17.113
이렇게 되면 최적의 Learning rate를 효율적으로
탐색할 수 없을 수도 있기 때문입니다.

01:14:17.113 --> 01:14:20.485
실제로 최적의 값이 1E-5에 근처에 존재할 수도 있는 것입니다.
어쩌면 1E-6 쯤에 있을지도 모릅니다.

01:14:20.485 --> 01:14:23.494
탐색 범위를 조금 이동시킨다면 더 좋은
범위를 찾을 수 있을지도 모릅니다.

01:14:23.494 --> 01:14:32.839
당연히 여러분은 최적의 값이 내가 정한 범위의 중앙 쯤에
위치하도록 범위를 잘 설정해 주는 것이 중요합니다.

01:14:36.224 --> 01:14:43.741
하이퍼파라미터를 찾는 또 다른 방법은
grid search를 이용하는 것입니다.

01:14:43.741 --> 01:14:49.731
하이퍼 파라미터를 고정된 값과 간격으로 샘플링하는 것입니다.

01:14:49.731 --> 01:15:02.334
하지만 실제로는 grid search보다는
이전 처럼 random search를 하는 것이 더 좋습니다.

01:15:02.334 --> 01:15:10.876
Random search를 하는 경우 여기 오른쪽에 있는 것과 같은
결과를 얻을 수 있을 것입니다.

01:15:10.876 --> 01:15:19.816
Random이 더 좋은 이유는 바로 내 모델이 어떤 특정 파라미터의
변화에 더 민감하게 반응을 하고 있다고 생각해 보면 (노란 &lt; 초록)

01:15:19.816 --> 01:15:24.669
이 함수가 더 비효율적인 dimentionality를 보인다고
할 수 있고 (노랑 에는 별로 영향을 안 받음)

01:15:24.669 --> 01:15:30.342
Random search는 중요한 파라미터(초록) 에게도
더 많은 샘플링이 가능하므로

01:15:30.342 --> 01:15:38.326
위에 그려놓은 초록색 함수를 더 잘 찾을 수 있을 것입니다.

01:15:38.326 --> 01:15:46.459
Grid Layout 에서는 단지 세 번의 샘플링 밖에 할 수 없으므로
Good region이 어디인지 제대로 찾을 수 없습니다.

01:15:46.459 --> 01:15:55.685
Random search를 사용하면 important variable 에서 더
다양한 값을 샘플링 할 수 있으므로 더 좋습니다.

01:15:55.685 --> 01:16:00.427
하이퍼파라미터에는 어떤 것이 있을까 생각해보면
Learning rate가 있겠죠 이미 다뤄봤습니다.

01:16:00.427 --> 01:16:07.697
그 밖에 decay schedule, update type,
regularization, network architecture,

01:16:07.697 --> 01:16:12.405
히든 유닛과 depth의 수 등 이 모든 하이퍼파라미터를
전부 다 최적화 시킬 수 있습니다.다.

01:16:12.405 --> 01:16:16.928
일부는 이번 시간에 배운 내용이고 나머지는
다음 강의에서 좀 더 다뤄보도록 하겠습니다.

01:16:16.928 --> 01:16:24.781
이 과정은 마치 턴테이블에 knobs를 조절하는 과정이라 할 수 있습니다.

01:16:26.667 --> 01:16:32.260
여러분은 neural networks practitioner 손실함수의
출력이 음악이라고 생각해 보면

01:16:32.260 --> 01:16:36.313
적절한 출력(loss)을 내보이기 위해서 모든 것들을
적절히 조절하는 것이라고 보시면 될 것입니다.

01:16:36.313 --> 01:16:40.480
때문에 이는 일종의 art라고 할 수 있습니다.

01:16:42.194 --> 01:16:50.277
실제로 여러분은 하이퍼파라미터 최적화와
Cross-validation 정말 많이 해야 할 것입니다.

01:16:50.277 --> 01:17:00.368
cross validation으로 엄청나게 많은 하이퍼파라미터를 직접 돌려보고
모니터해서 어떤 값이 좋고 나쁜지를 확인해야 합니다.

01:17:00.368 --> 01:17:07.895
여기 있는 loss curve를 보면서 좋은 것을 찾아서
시도해보는 일을 계속 반복해야 합니다.

01:17:07.895 --> 01:17:14.380
loss curve를 모니터링 하는데 있어서 앞서 언급했듯
learning rate이 정말 중요합니다.

01:17:15.311 --> 01:17:20.654
그리고 loss curve를 보고 어떤 learning rate가 좋고
나쁜지를 알아볼 수 있습니다.

01:17:20.654 --> 01:17:34.060
Loss가 발산하면 learning rate가 높은 것이고
너무 평평(linear)하다 싶으면 너무 낮은 것입니다.

01:17:34.060 --> 01:17:41.660
가파르게 내려가다가 어느순간 정체기가 생기면
이 또한 여전히 너무 높다는 의미입니다.

01:17:41.660 --> 01:17:48.460
learning step이 너무 크게 점프해서 적절한 local optimum
에 도달하지 못하는 경우입니다.

01:17:48.460 --> 01:17:53.572
최적의 learning rate는 대게 이런식입니다 (파란색)
비교적 가파르게 내려가면서도

01:17:53.572 --> 01:17:57.993
지속적으로 잘 내려간다면 현재 learning rate를
유지해도 좋습니다.

01:17:57.993 --> 01:18:02.160
이들은 모두 여러분들이 실제 학습을 할 때 겪게 될 것들입니다.

01:18:03.522 --> 01:18:12.637
끝날 시간이 거의 다 되서 한 가지만 더 알아보겠습니다.
loss curve에 관한 것입니다.

01:18:12.637 --> 01:18:23.567
loss가 평평하다가 갑자기 가파르게 내려가는 것을 보게
된다면 이는 초기화의 문제일 수 있습니다.

01:18:23.567 --> 01:18:36.383
gradient의 backpropb이 초기에는 잘 되지 않다가
학습이 진행되면서 회복이 되는 경우입니다.

01:18:36.383 --> 01:18:47.901
그리고 다음은 여러분이 accuracy를 모니터링 하다보면
겪을 수 있는 일입니다.

01:18:48.826 --> 01:18:54.860
만일 train_acc와 va_acc가 큰 차이를 보인다면

01:18:54.860 --> 01:18:59.652
이를 overfit 일 지도 모릅니다. 따라서 regularization
의 강도를 높혀야 할 지도 모릅니다.

01:18:59.652 --> 01:19:08.137
gap이 없다면 아직 overfit하지 않은 것이고 capacity을 높힐
수 있는 충분한 여유가 있다는 것을 의미합니다.

01:19:08.137 --> 01:19:13.998
그리고 보통 우리는 가중치의 크기 대비 가중치 업데이트의
비율을 지켜볼 필요가 있습니다.

01:19:13.998 --> 01:19:21.428
우선 파라미터의 norm을 구해서 가중치의
규모를 계산합니다.

01:19:21.428 --> 01:19:26.353
그리고 업데이트 사이즈 또한 norm을 통해 구할 수 있고
이로 얼마나 크게 업데이트 되는지를 알 수 있습니다.

01:19:26.353 --> 01:19:30.025
우리는 이 비율이 대략 0.001 정도 되길 원합니다.

01:19:30.025 --> 01:19:35.598
이 값은 변동이 커서 정확하지 않을 수 있습니다.

01:19:35.598 --> 01:19:41.477
하지만 업데이트가 지나치게 크거나 작은지에 대한
감을 어느정도 가질 수는 있습니다.

01:19:41.477 --> 01:19:43.637
너무 업데이트가 지나치거나 아무 업데이트도 없으면 안되겠죠

01:19:43.637 --> 01:19:47.811
여러분의 문제가 뭔지 디버깅할 때 유용할 것입니다.

01:19:49.843 --> 01:19:59.016
자 오늘 배운 내용을 요약해보면 활성 함수와 데이터 전처리
그리고 가중치 초기화, Batch Norm, 학습 과정 준비하기

01:19:59.016 --> 01:20:01.694
하이퍼 파라미터 최적화를 배웠습니다.

01:20:01.694 --> 01:20:05.338
각각의 주제에서 명심해야 할 것들이 있었습니다.

01:20:05.338 --> 01:20:08.491
ReLU를 사용하고(활성함수), 평균을 뺴고(데이터 전처리),
Xavier Initialization을 쓰고 (가중치 초기화)

01:20:08.491 --> 01:20:12.499
Batch Norm을 사용하고 Random Search를 통해
하이퍼파라미터를 찾습니다.

01:20:12.499 --> 01:20:19.355
다음 시간에는 다른 주제로 Neural Network에
대해 조금 더 공부해 보겠습니다. 감사합니다